/*********************************************************
   Copyright: (C) 2008-2010 by Steven Schveighoffer.
              All rights reserved

   License: Boost Software License version 1.0

   Permission is hereby granted, free of charge, to any person or organization
   obtaining a copy of the software and accompanying documentation covered by
   this license (the "Software") to use, reproduce, display, distribute,
   execute, and transmit the Software, and to prepare derivative works of the
   Software, and to permit third-parties to whom the Software is furnished to
   do so, all subject to the following:

   The copyright notices in the Software and this entire statement, including
   the above license grant, this restriction and the following disclaimer, must
   be included in all copies of the Software, in whole or in part, and all
   derivative works of the Software, unless such copies or derivative works are
   solely in the form of machine-executable object code generated by a source
   language processor.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.

**********************************************************/
module dcollections.model.Map;

public import dcollections.model.Keyed;

/**
 * A Map collection uses keys to map to values.  This can only have one
 * instance of a particular key at a time.
 */
interface Map(K, V) : Keyed!(K, V)
{
    /**
     * set all the elements from the given keyed iterator in the map.  Any key
     * that already exists will be overridden.
     *
     * Returns this.
     */
    Map set(KeyedIterator!(K, V) source);

    /**
     * set all the elements from the given associative array in the map.  Any
     * key that already exists wil be overridden.
     *
     * Returns this.
     */
    Map set(V[K] source);

    /**
     * Remove all the given keys from the map.
     *
     * return this.
     */
    Map remove(Iterator!(K) subset);

    /**
     * Remove all the given keys from the map.
     *
     * return this.
     */
    Map remove(K[] subset...);

    version(testcompiler)
    {

    /**
     * Remove a range of keys from the map.
     *
     * return this.
     *
     * TODO: rename to removeKeys
     */
    auto removeRange(R)(R range) if (isInputRange!R && is(isElementType!R == K))
    {
        foreach(k; range)
            removeAt(k);
        return this;
    }
    }

    /**
     * Remove all the keys that are not in the given iterator.
     *
     * returns this.
     */
    Map intersect(Iterator!(K) subset);

    /**
     * Remove all the keys that are not in the given array.
     *
     * returns this.
     */
    Map intersect(K[] subset...);

    /**
     * Get a set of the keys that the map contains.  This is not a copy of the
     * keys, but an actual "window" into the keys of the map.  If you add
     * values to the map, they will show up in the keys iterator.
     *
     * This is not in Keyed, because some Keyed containers have simple index
     * keys, and so this would be not quite that useful there.
     */
    Iterator!(K) keys();

    /**
     * clear all elements in the collection (part of collection
     * pseudo-interface)
     */
    Map clear();

    /**
     * dup the collection (part of collection pseudo-interface)
     */
    Map dup();

    /**
     * covariant set (from Keyed)
     */
    Map set(K key, V value);

    /**
     * compare two maps.  Returns true if both maps have the same number of
     * elements, and both maps have elements whose keys and values are equal.
     *
     * If o is not a map, then 0 is returned.
     */
    bool opEquals(Object o);

    /**
     * compare map to an AA
     */
    bool opEquals(V[K] other);
}
